package dbUtils

import (
	"fmt"
	"gitee.com/lv_baobao/gcore"
	"github.com/ahmetb/go-linq/v3"
	"strings"
	"sync"
	"time"

	//_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
	_ "github.com/jinzhu/gorm/dialects/mssql"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"xorm.io/core"
)

var _dbConfigs = make([]gcore.DbConfig, 0)
var _showSql = true

func init() {
	config := gcore.NewAppSettingsHelper().GetAppConfig()
	_dbConfigs = config.DBConfig
	_showSql = config.ShowSql
}

type DbHelper struct {
	dbConfigs []gcore.DbConfig
	engines   map[string]*xorm.Engine
	lock      sync.Mutex
}

var _dbHelperOnce sync.Once
var _dbHelper *DbHelper

func NewDbHelper() *DbHelper {
	_dbHelperOnce.Do(func() {
		_dbHelper = new(DbHelper)
		_dbHelper.dbConfigs = _dbConfigs
		_dbHelper.engines = make(map[string]*xorm.Engine)
	})
	return _dbHelper
}

func (db *DbHelper) GetWriteDb() *xorm.Engine {
	return db.GetDbByKey("writedb")
}

func (db *DbHelper) GetReadDb() *xorm.Engine {
	return db.GetDbByKey("readdb")
}

func (db *DbHelper) GetEngineKey(dbConfig *gcore.DbConfig) string {
	var engineKey = fmt.Sprintf("%s%s", dbConfig.DataBaseType, dbConfig.ConnectionString)
	return engineKey
}

func (db *DbHelper) GetDbByKey(dbKey string) *xorm.Engine {
	dbConfig := db.GetDbConfig(dbKey)
	//var engineKey = db.GetEngineKey(&dbConfig)
	//var x, ok = db.engines[engineKey]
	//if ok {
	//	return x
	//}
	//db.lock.Lock()
	//defer db.lock.Unlock()
	//x, ok = db.engines[engineKey]
	//if ok {
	//	return x
	//}
	//var err error
	//x, err = xorm.NewEngine(dbConfig.DataBaseType, dbConfig.ConnectionString)
	//if err != nil {
	//	panic(err)
	//}
	//x.SetTableMapper(core.SameMapper{})
	//x.SetColumnMapper(core.SameMapper{})
	//x.ShowExecTime(true)
	//x.SetConnMaxLifetime(10 * time.Second) //How long will the idle connection in the connection pool remain? 连接池中的空闲连接保持多久
	//x.SetMaxOpenConns(100)                 //Maximum number of connections allowed to open 允许打开的最大连接数
	//x.SetMaxIdleConns(10)
	//x.ShowSQL(_showSql)
	//db.engines[engineKey] = x
	//return x
	return db.GetDbByDbConfig(dbConfig)
}

func (db *DbHelper) GetDbByDbConfig(dbConfig *gcore.DbConfig) *xorm.Engine {
	var engineKey = db.GetEngineKey(dbConfig)
	var x, ok = db.engines[engineKey]
	if ok {
		return x
	}
	db.lock.Lock()
	defer db.lock.Unlock()
	x, ok = db.engines[engineKey]
	if ok {
		return x
	}
	var err error
	x, err = xorm.NewEngine(dbConfig.DataBaseType, dbConfig.ConnectionString)
	if err != nil {
		panic(err)
	}
	x.SetTableMapper(core.SameMapper{})
	x.SetColumnMapper(core.SameMapper{})
	x.ShowExecTime(true)
	x.SetConnMaxLifetime(10 * time.Second) //How long will the idle connection in the connection pool remain? 连接池中的空闲连接保持多久
	x.SetMaxOpenConns(100)                 //Maximum number of connections allowed to open 允许打开的最大连接数
	x.SetMaxIdleConns(10)
	x.ShowSQL(_showSql)
	db.engines[engineKey] = x
	return x
}

func (db *DbHelper) GetDialect(dbKey string) string {
	dbConfig := db.GetDbConfig(dbKey)
	return dbConfig.DataBaseType
}

func (db *DbHelper) GetTargetDbConfig(dbKey string) *gcore.DbConfig {
	dbConfig := db.GetDbConfig(dbKey)
	return dbConfig.TargetDataBase
}

func (db *DbHelper) GetDbConfig(dbKey string) *gcore.DbConfig {
	if dbKey == "" {
		dbKey = "writedb"
	}
	var dbConfigs = db.dbConfigs
	var firstConfig = linq.From(dbConfigs).Where(func(i interface{}) bool {
		var f = i.(gcore.DbConfig)
		return strings.ToLower(f.DataBaseKey) == strings.ToLower(dbKey)
	}).First()
	if firstConfig == nil {
		panic(fmt.Sprintf("dbkey【%s】 未找到", dbKey))
	}
	dbConfig := firstConfig.(gcore.DbConfig)
	return &dbConfig
}
